import tkinter as tk
from tkinter import filedialog, ttk, messagebox
import os
from datetime import datetime
import re

class JSFileMergerApp:
    def __init__(self, root):
        self.root = root
        self.root.title("JavaScript文件整合工具")
          # 核心优化：设置固定初始宽度和最小宽度，高度自适应
        # self.root.geometry("750x0")  # 宽度固定为750，高度初始为0（让内容决定高度）
        self.root.minsize(width=750, height=0)  # 最小宽度750，最小高度0（不限制高度）
        # self.root.geometry("750x550")
        
        # 设置中文字体支持
        self.style = ttk.Style()
        self.style.configure("TLabel", font=("SimHei", 10))
        self.style.configure("TButton", font=("SimHei", 10))
        self.style.configure("TFrame", padding=10)
        self.style.configure("Accent.TButton", font=("SimHei", 10, "bold"))
        
        # 存储文件路径
        self.main_file = tk.StringVar()
        self.lib_files = []
        # 新增：设置文件间空行数（可自定义）
        self.line_gap = 15  # 默认15行空行分隔不同文件
        
        # 创建UI
        self.create_widgets()
    
    def create_widgets(self):
        # 主框架
        main_frame = ttk.Frame(self.root, padding="20")
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 1. 入口文件选择
        ttk.Label(main_frame, text="1. 选择入口JS文件 (如main.js):", font=("SimHei", 12, "bold")).pack(anchor=tk.W, pady=(0, 5))
        
        main_file_frame = ttk.Frame(main_frame)
        main_file_frame.pack(fill=tk.X, pady=(0, 15))
        
        ttk.Entry(main_file_frame, textvariable=self.main_file, width=50).pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 10))
        ttk.Button(main_file_frame, text="浏览...", command=self.select_main_file).pack(side=tk.RIGHT)
        
        # 2. 依赖库文件选择
        ttk.Label(main_frame, text="2. 选择依赖JS文件 (如frame.js):", font=("SimHei", 12, "bold")).pack(anchor=tk.W, pady=(0, 5))
        
        lib_files_frame = ttk.Frame(main_frame)
        lib_files_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 15))
        
        self.lib_files_listbox = tk.Listbox(lib_files_frame, selectmode=tk.EXTENDED, width=70, height=12)
        self.lib_files_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        scrollbar = ttk.Scrollbar(lib_files_frame, orient=tk.VERTICAL, command=self.lib_files_listbox.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.lib_files_listbox.config(yscrollcommand=scrollbar.set)
        
        buttons_frame = ttk.Frame(main_frame)
        buttons_frame.pack(fill=tk.X, pady=(0, 15))
        
        ttk.Button(buttons_frame, text="添加文件...", command=self.add_lib_files).pack(side=tk.LEFT, padx=(0, 10))
        ttk.Button(buttons_frame, text="移除选中", command=self.remove_lib_files).pack(side=tk.LEFT)
        
        # 3. 整合选项（新增空行数设置）
        options_frame = ttk.Frame(main_frame)
        options_frame.pack(fill=tk.X, pady=(0, 15))
        
        # 空行数设置
        ttk.Label(options_frame, text="文件间空行数:", font=("SimHei", 10)).pack(anchor=tk.W, pady=(5, 2))
        line_gap_frame = ttk.Frame(options_frame)
        line_gap_frame.pack(anchor=tk.W, pady=(0, 5))
        
        self.line_gap_var = tk.IntVar(value=self.line_gap)
        ttk.Entry(line_gap_frame, textvariable=self.line_gap_var, width=5).pack(side=tk.LEFT, padx=(0, 10))
        ttk.Label(line_gap_frame, text="行（建议10-20行，用于区分不同文件）").pack(side=tk.LEFT)
        
        # 导入语句移除选项
        self.remove_requires = tk.BooleanVar(value=True)
        ttk.Checkbutton(
            options_frame, 
            text="移除require导入语句 (如 require('./frame'))", 
            variable=self.remove_requires
        ).pack(anchor=tk.W, pady=(5, 2))
        
        self.remove_imports = tk.BooleanVar(value=True)
        ttk.Checkbutton(
            options_frame, 
            text="移除import导入语句 (如 import * from './frame')", 
            variable=self.remove_imports
        ).pack(anchor=tk.W, pady=(2, 5))
        
        # 4. 整合按钮
        ttk.Button(
            main_frame, 
            text="整合为单个JS文件", 
            command=self.merge_files,
            style="Accent.TButton"
        ).pack(pady=20)
        
        # 状态标签
        self.status_var = tk.StringVar(value="请选择文件进行整合")
        ttk.Label(main_frame, textvariable=self.status_var, foreground="blue").pack(side=tk.BOTTOM, pady=10)
    
    def select_main_file(self):
        """选择入口JS文件"""
        file_path = filedialog.askopenfilename(
            title="选择入口JS文件",
            filetypes=[("JavaScript文件", "*.js"), ("所有文件", "*.*")]
        )
        if file_path:
            self.main_file.set(file_path)
            self.status_var.set(f"已选择入口文件: {os.path.basename(file_path)}")
    
    def add_lib_files(self):
        """添加依赖JS文件"""
        file_paths = filedialog.askopenfilenames(
            title="选择依赖JS文件",
            filetypes=[("JavaScript文件", "*.js"), ("所有文件", "*.*")]
        )
        
        for file_path in file_paths:
            if file_path not in self.lib_files and file_path != self.main_file.get():
                self.lib_files.append(file_path)
                self.lib_files_listbox.insert(tk.END, os.path.basename(file_path))
        
        if file_paths:
            self.status_var.set(f"已添加 {len(file_paths)} 个依赖文件")
    
    def remove_lib_files(self):
        """移除选中的依赖文件"""
        selected_indices = sorted(self.lib_files_listbox.curselection(), reverse=True)
        if not selected_indices:
            messagebox.showinfo("提示", "请先选择要移除的文件")
            return
        
        for index in selected_indices:
            self.lib_files_listbox.delete(index)
            del self.lib_files[index]
        
        self.status_var.set(f"已移除 {len(selected_indices)} 个文件")
    
    def remove_import_statements(self, content, lib_name):
        """移除各种格式的导入语句"""
        # 处理require语句 - 支持大小写不敏感
        require_pattern = re.compile(
            rf'require\(\s*["\']\.\/{lib_name}["\']\s*\)', 
            re.IGNORECASE
        )
        content = require_pattern.sub('', content)
        
        # 处理import语句 - 支持多种格式和大小写不敏感
        import_patterns = [
            # import ... from './lib'
            re.compile(rf'import\s+.*?\s+from\s+["\']\.\/{lib_name}["\']\s*;?', re.IGNORECASE),
            # import './lib'
            re.compile(rf'import\s+["\']\.\/{lib_name}["\']\s*;?', re.IGNORECASE),
            # import * as ... from './lib'
            re.compile(rf'import\s+\*\s+as\s+.*?\s+from\s+["\']\.\/{lib_name}["\']\s*;?', re.IGNORECASE),
            # import { ... } from './lib'
            re.compile(rf'import\s+{{.*?}}\s+from\s+["\']\.\/{lib_name}["\']\s*;?', re.IGNORECASE)
        ]
        
        for pattern in import_patterns:
            content = pattern.sub('', content)
        
        # 清除空行
        return '\n'.join([line for line in content.split('\n') if line.strip()])
    
    def merge_files(self):
        """整合JS文件，支持自定义文件间空行数和移除导入语句"""
        if not self.main_file.get():
            messagebox.showerror("错误", "请先选择入口JS文件")
            return
        
        # 获取用户设置的空行数（限制在5-50行，避免不合理值）
        try:
            line_gap = self.line_gap_var.get()
            if line_gap < 5 or line_gap > 50:
                messagebox.showwarning("提示", "空行数建议设置在5-50行之间，已自动调整为15行")
                line_gap = 15
        except:
            line_gap = 15  # 异常时使用默认值
        
        # 选择保存位置
        save_path = filedialog.asksaveasfilename(
            title="保存整合文件",
            defaultextension=".js",
            filetypes=[("JavaScript文件", "*.js"), ("所有文件", "*.*")]
        )
        
        if not save_path:
            return
        
        try:
            with open(save_path, 'w', encoding='utf-8') as outfile:
                # 写入文件头信息
                outfile.write("// 整合后的JavaScript文件\n")
                outfile.write(f"// 生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
                outfile.write(f"// 包含文件: {os.path.basename(self.main_file.get())}")
                for lib_file in self.lib_files:
                    outfile.write(f", {os.path.basename(lib_file)}")
                outfile.write("\n\n")
                
                # 写入依赖文件内容（添加空行分隔）
                for i, lib_file in enumerate(self.lib_files):
                    # 写入文件开始标记
                    outfile.write(f"// ====== 开始: {os.path.basename(lib_file)} ======\n")
                    # 写入文件内容
                    with open(lib_file, 'r', encoding='utf-8') as infile:
                        content = infile.read()
                        outfile.write(content)
                    # 写入文件结束标记
                    outfile.write(f"\n// ====== 结束: {os.path.basename(lib_file)} ======\n")
                    # 添加空行（最后一个依赖文件后也加空行，与入口文件分隔）
                    outfile.write('\n' * line_gap)
                
                # 写入入口文件内容（处理导入语句）
                outfile.write(f"// ====== 开始: {os.path.basename(self.main_file.get())} (入口文件) ======\n")
                with open(self.main_file.get(), 'r', encoding='utf-8') as infile:
                    content = infile.read()
                    
                    # 处理导入语句
                    if self.remove_requires.get() or self.remove_imports.get():
                        for lib_file in self.lib_files:
                            lib_name = os.path.splitext(os.path.basename(lib_file))[0]
                            content = self.remove_import_statements(content, lib_name)
                    
                    outfile.write(content)
                outfile.write(f"\n// ====== 结束: {os.path.basename(self.main_file.get())} ======\n")
            
            self.status_var.set(f"文件已成功整合至: {save_path}")
            messagebox.showinfo("成功", f"文件已成功整合至:\n{save_path}\n文件间已添加 {line_gap} 行空行分隔")
            
        except Exception as e:
            self.status_var.set(f"整合失败: {str(e)}")
            messagebox.showerror("错误", f"整合文件时发生错误:\n{str(e)}")

if __name__ == "__main__":
    root = tk.Tk()
    app = JSFileMergerApp(root)
    root.mainloop()